package myEddy.tuple;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Set;

/**
 * Class representing a 'tuple'.
 * The tuple has two array of string: one for the name of the column, an other one for the corresponding values.
 * It contains also an array containing the original tables name.
 * 
 * @author Nathan Ramoly
 *
 */
public class Tuple {
	
	/** Attributes **/
	
	/**
	 * List of tables 'owning' this tuple.
	 * It may have several tables, for instance when making a joint.
	 */
	private ArrayList<String> tables;
	
	/**
	 * The tuple itself.
	 * The key correspond to the column name.
	 * The rest corresponds to the values
	 */
	private HashMap<String, String> tuple;
	
	/**
	 * Bitmap of operator that it needs to go in.
	 * Shall be set by the query manager/scrambler.
	 */
	private BitSet to_do_bitmap;
	
	/**
	 * Bitmap of operator that has already work on this tuple.
	 * Shall be set by the query manager/scrambler
	 */
	private BitSet done_bitmap;
	
	
	
	/** methods **/
	
	/**
	 * Constructor
	 * @param table_name Table owning the tuple
	 */
	public Tuple( String table_name )
	{
		tables = new ArrayList<String>();
		tables.add(table_name);	
		
		tuple = new HashMap<String, String>();
		
		to_do_bitmap = new BitSet();
		done_bitmap = new BitSet();
	}
	
	/**
	 * Constructor
	 * @param new_tables Tables owning the tables
	 * @param new_tuple The new tuples itself
	 */
	public Tuple( ArrayList<String> new_tables, HashMap<String, String> new_tuple  )
	{
		tables = new ArrayList<String>(new_tables);
		tuple = new HashMap<String, String>(new_tuple);
		
		to_do_bitmap = new BitSet();
		done_bitmap = new BitSet();
	}
	
	/**
	 * Constructor from another tuple
	 */
	public Tuple( Tuple orig )
	{		
		tables = new ArrayList<String>(orig.getTables());
		
		tuple = new HashMap<String, String>();
		
		//Add the elements
        Set<String> columns = orig.getColumns();        
        //Joining
        for( String column : columns )
        {
            addElement(column, orig.getElement(column) );
        }
		
		to_do_bitmap = new BitSet();
		to_do_bitmap.or(orig.getToDoBitmap());
		
		done_bitmap = new BitSet();
		done_bitmap.or(orig.getDoneBitmap());
	}
	
	
	/**
	 * Add (or update if it exists) the column with the wanted value
	 * @param column_name Name of the column to add/modify
	 * @param value String value of the column
	 */
	public void addElement(String column_name, String value)
	{
		tuple.put(column_name, value);
		
	}
	
	/**
	 * Remove the wanted column
	 * @param column_name The column to exterminate
	 */
	public void removeElement(String column_name)
	{
		tuple.remove(column_name);
	}
	
	/**
	 * Add an owning table
	 * @param table_name Name of the new table
	 */
	public void addTable( String table_name )
	{
		tables.add(table_name);		
	}
	
	/**
	 * Remove table.
	 * @param table_name Table to remove
	 */
	public void remove(String table_name)
	{
		tables.remove(table_name);		
	}
	
	/**
	 * Reset the to_do_bitmap 
	 * @param new_to_do New bitmap.
	 */
	public void setToDoBitmap( BitSet new_to_do )
	{
		to_do_bitmap = new_to_do;
	}
	
	/**
	 * Reset the done_bitmap 
	 * @param new_done New bitmap.
	 */
	public void setDoneBitmap( BitSet new_done )
	{
		done_bitmap = new_done;
	}
	
	
	
	/**
	 * Get the current number of column.
	 * @return The number of column
	 */
	public int getColumnNumber()
	{
		return tuple.size();
	}
	
	/**
	 * Get the value of the wanted column
	 * @param column_name Column to read
	 * @return Value of this column
	 */
	public String getElement( String column_name )
	{
		return tuple.get(column_name);
	}
	
	/**
	 * Get the set of key of the tuple
	 * @return All columns
	 */
	public Set<String> getColumns()
	{
		return tuple.keySet();
	}
	
	/**
	 * Get all the owing tables
	 * @return The owning tables
	 */
	public ArrayList<String> getTables()
	{
		return tables;
	}
	
	/**
	 * Return to_do_bitmap
	 * @return The bitmap of remaining operator to go in
	 */
	public BitSet getToDoBitmap()
	{
		return to_do_bitmap;
	}
	
	/**
	 * Return done_bitmap
	 * @return The bitmap of operator already went in
	 */
	public BitSet getDoneBitmap()
	{
		return done_bitmap;
	}
}
